/*
Copyright (C) 2010  Christoph Schnack, Berlin (Germany)

This file is part of Tribuit.

    Tribuit is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    Tribuit is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with Tribuit.  If not, see <http://www.gnu.org/licenses/>.
*/
package PictureDescription;

import java.awt.*;
import java.io.*;
import java.util.HashMap;
import java.util.Vector;

import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

import PictureDescription.PictureTagUnit.*;
import Settings.Settings;
import GuiTools.*;
/**
 * Holds all picture data and provides methods to alter it.
 * @author Christoph Schnack
 *
 */
public class PictureStorage {
	Settings SET;
	boolean LOADED,LOADING;
	Vector<PictureCollection> COLLECTIONS;
	HashMap<String,Lesson> LESSONS;
	
	public PictureStorage(Settings set){
		SET=set;
		COLLECTIONS=new Vector<PictureCollection>();
		LESSONS = new HashMap<String,Lesson>();
		LOADED=initStorage();
	}
	
	public boolean hasCollections(){
		return (COLLECTIONS.isEmpty())?false:true;
	}
	
	public String[] getCollectionNames(){
		if(hasCollections()){
			String[] result = new String[COLLECTIONS.size()];
			for(int i=0;i<COLLECTIONS.size();i++){
				result[i]=COLLECTIONS.elementAt(i).getName();
			}
			return result;
		}
		else{
			return new String[0];
		}
	}
	
	public PictureCollection getCollection(String nameArg){
		if(hasCollections()){
			for(int i=0;i<COLLECTIONS.size();i++){
				if(COLLECTIONS.elementAt(i).getName().equals(nameArg)) return COLLECTIONS.elementAt(i);
			}
		}
		return null;
	}
	
	public void deletePictureUnitInCollection(String pu,String col){
		File f = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+col+File.separator+pu);
		File[] files = f.listFiles();
		for(File fl : files){
			fl.delete();
		}
		f.delete();
		getCollection(col).deletePictureUnit(pu);
	}
	
	public void editPictureUnitInCollection(PictureUnit pu,String picturePath,String col){
		if(picturePath!=null){
			copyImage(picturePath,GuiTools.PATHTOPICTUREMAPS+File.separator+col+File.separator+pu.getName());
		}
		getCollection(col).replacePictureUnit(pu.getName(),pu);
		saveUnit(col,pu);
	}
	
	public void createCollection(String name){
		File f = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+name);
		if(f.mkdir())addCollection(name);
	}
	
	public void addCollection(String name){
		if(!hasCollection(name)) COLLECTIONS.add(new PictureCollection(SET,name));
	}
	
	
	public boolean hasCollection(String name){
		for(int i=0;i<COLLECTIONS.size();i++){
			if(COLLECTIONS.elementAt(i).getName().equals(name))return true;
		}
		return false;
	}
	
	public void deleteCollection(String toDelete){
		if(!COLLECTIONS.isEmpty()){
			for(int i=0;i<COLLECTIONS.size();i++){
				if(COLLECTIONS.elementAt(i).getName().equals(toDelete)){
					COLLECTIONS.removeElementAt(i);
				}
			}
			File f = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+toDelete);
			String[] dirs = f.list();
			if(dirs.length>0){
				File tmpF;
				File[] files;
				for(String dir : dirs){
					tmpF = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+toDelete+File.separator+dir);
					files = tmpF.listFiles();
					if(files.length>0){
						for(File fl : files){
							fl.delete();
						}
					}
					tmpF.delete();
				}
			}
			f.delete();
			deleteCollectionFromLessons(toDelete);
			saveLessons();
		}
	}
	
	public void editCollectionName(String oldName, String newName){
		for(int i=0;i<COLLECTIONS.size();i++){
			if(COLLECTIONS.elementAt(i).getName().equals(oldName)){
				COLLECTIONS.elementAt(i).setName(newName);
				File f = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+oldName);
				f.renameTo(new File(GuiTools.PATHTOPICTUREMAPS+File.separator+newName));
			}
		}
		changeCollectionNameInLessons(oldName, newName);
		saveLessons();
	}
	
	public void addPictureUnitToCollection(PictureUnit pu,String col){
		getCollection(col).addPU(pu);
		saveUnit(col,pu);
	}
	
	public void createPUToVoc(PictureUnit pu,String picturePath, String coll){
		copyImage(picturePath,GuiTools.PATHTOPICTUREMAPS+File.separator+coll+File.separator+pu.getName());
		addPictureUnitToCollection(pu,coll);
	}
	
	public void copyImage(String source,String destination){
		File f = new File(destination);
		if(!f.exists()){
			if(!f.mkdir()){
				JOptionPane.showMessageDialog(null, SET.getLanguage().getErrorNoRights());
				return;
			}
		}
		File pic = new File(source);
		File dest = new File(f.getPath()+File.separator+"image");
		try{
			if(!dest.exists())dest.createNewFile();
			FileInputStream fis = new FileInputStream(pic);
			FileOutputStream fos = new FileOutputStream(dest);
			byte[] bytes = new byte[1024];
			int len;
			while((len=fis.read(bytes))>0){
				fos.write(bytes,0,len);
			}
			fis.close();
			fos.close();
		}
		catch(Exception e){
			e.printStackTrace();
		}
	}
	
	public boolean isLoaded(){
		return LOADED;
	}
	
	public boolean initStorage(){
		try{
			if(SET.isVerbose())System.out.println("\n#---INITIALZING PICTUREMAP-STORAGE---");
			File PATH = new File(GuiTools.PATHTOPICTUREMAPS);
			boolean directoryExists = PATH.isDirectory();
			if(directoryExists){
			    if(SET.isVerbose())System.out.println("#PICTUREMAP-STORAGE PATH FOUND: "+PATH.getPath());
		    	return load();
			}
			else{
				if(SET.isVerbose())System.out.print("#PICTURE-STORAGE PATH NOT FOUND\n#CREATING PATH: '"+PATH.getPath() + "' ...");
		    	if(PATH.mkdir()){
					if(SET.isVerbose()) System.out.println("SUCCESSFULLY");
					return true;
		    	}
		    	else{
					if(SET.isVerbose()) System.out.println("#FAILED!!! ");
					JOptionPane.showMessageDialog(null, SET.getLanguage().getErrorNoRights());
					return false;
		    	}
			}
		}
		catch(Exception e){
			e.printStackTrace();
			return false;
		}
	}
	
	public boolean load(){
		if(SET.isVerbose()) System.out.println("#COMMENCING SCAN FOR PICTURE COLLECTIONS");
		try{
			LOADING = true;
			File dir = new File(GuiTools.PATHTOPICTUREMAPS);
			String[] collectionsList = dir.list();
			int colLength = collectionsList.length;
			if(SET.isVerbose()) System.out.println("#picture collections: "+colLength);
			if(colLength>0){
				File collectionPath,puData;
				String[] picts;
				for(String collection : collectionsList){
					if(SET.isVerbose()) System.out.println("# "+collection);
					addCollection(collection);
					collectionPath = new File(GuiTools.PATHTOPICTUREMAPS+File.separator+collection);
					picts = collectionPath.list();
					if(picts.length>0){
						String line,loads="";
						String[] split1,split2;
						PictureUnit tmpUnit;
						Vector<PictureNameUnit> pnuVector;
						for(String pictureUnit : picts){
							pnuVector = new Vector<PictureNameUnit>();
							puData = new File(collectionPath.getPath()+File.separator+pictureUnit+File.separator+"data");
							if(puData.exists()){
								BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(puData),"UTF-8"));
								line = null;
								loads = "";
								while((line = reader.readLine()) != null){
									loads=loads+line;
								}
								//name, title, titleInfo, section, pictureUnit
								split1 = loads.split("#");
								if(!split1[4].equals("~")){
									split2 = split1[4].split("<");
									String[] split3;
									Vector<PictureTagUnit> ptuv;
									PictureTagUnit ptu;
									Vector<TADE> tadeV;
									String pnuName,pnuInfo;
									for(String s : split2){
										if(s!=null && !s.equals("")){
											ptuv = new Vector<PictureTagUnit>();
											split3 = s.split(":");
											pnuName = split3[0];
											pnuInfo = (split3[1].equals("~"))?"":split3[1];
											String[] tagSplit = split3[2].split(">"),tag,point,col,bgCol,flCol,tades;
											int radius;
											for(String ta : tagSplit){
												if(ta!=null && !ta.equals("")){
													tadeV = new Vector<TADE>();
													tag = ta.split(";");
													point = tag[0].split(",");
													radius = Integer.parseInt(tag[1]);
													col = tag[2].split(",");
													bgCol = tag[3].split(",");
													flCol = tag[4].split(",");
													ptu = new PictureTagUnit(tadeV,new Point(Integer.parseInt(point[0]),Integer.parseInt(point[1])),new Color(Integer.parseInt(col[0]),Integer.parseInt(col[1]),Integer.parseInt(col[2])),new Color(Integer.parseInt(bgCol[0]),Integer.parseInt(bgCol[1]),Integer.parseInt(bgCol[2])),new Color(Integer.parseInt(flCol[0]),Integer.parseInt(flCol[1]),Integer.parseInt(flCol[2])),radius );
													if(!tag[5].equals("~")){
														tades = tag[5].split("%");
														String type;
														String[] bgC,fC,pnt;
														for(String tade : tades){
															if(tade!=null && !tade.equals("")){
																String[] t = tade.split("=");
																tadeV = new Vector<TADE>();
																type = t[0];
																pnt = t[1].split(",");
																bgC = t[2].split(",");
																fC = t[3].split(",");
																ptu.addPictureTagRelated(type,new Point(Integer.parseInt(pnt[0]),Integer.parseInt(pnt[1])),new Color(Integer.parseInt(bgC[0]),Integer.parseInt(bgC[1]),Integer.parseInt(bgC[2])),new Color(Integer.parseInt(fC[0]),Integer.parseInt(fC[1]),Integer.parseInt(fC[2])) );
															}
														}
													}
													ptuv.add(ptu);
												}
											}
											pnuVector.add(new PictureNameUnit(pnuName,pnuInfo,ptuv));
										}
									}
								}
								tmpUnit = new PictureUnit(split1[0],(split1[1].equals("~"))?"":split1[1],(split1[2].equals("~"))?"":split1[2],split1[3],pnuVector);
								addPictureUnitToCollection(tmpUnit,collection);
							}
						}
					}
				}
			}
			loadLessons();
			LOADING=false;
		}
		catch(Exception e){
			e.printStackTrace();
			return false;
		}
		return true;
	}
	
	public boolean saveUnit(String colName,PictureUnit unit){
		if(!LOADING){
			String pathOfCollection = GuiTools.PATHTOPICTUREMAPS+File.separator+colName;
			String name = unit.getName(),title,titleInfo,section;
			StringBuffer sb = new StringBuffer();
			File permissionTest = new File(pathOfCollection+File.separator+name+File.separator+"data");
			if((permissionTest.exists() && permissionTest.canWrite())||!permissionTest.exists()){
				title = (unit.getTitle().equals(""))?"~":unit.getTitle();
				titleInfo = (unit.getTitleInfo().equals(""))?"~":unit.getTitleInfo();
				section = unit.getSection();
				sb.append(name+"#"+title+"#"+titleInfo+"#"+section+"#");
				if(unit.hasPictureNameUnits()){
					Vector<PictureNameUnit> pnus = unit.getTags();
					PictureNameUnit tmpUnit;
					String pnuName,info;
					for(int k=0;k<pnus.size();k++){
						tmpUnit = pnus.elementAt(k);
						pnuName = tmpUnit.getName();
						info = (tmpUnit.getInfoText().equals(""))?"~":tmpUnit.getInfoText();
						sb.append(pnuName+":"+info+":");
						Vector<PictureTagUnit> ptus = tmpUnit.getTags();
						PictureTagUnit ptu;
						Point center;
						Color shapeCol,bgCol,flashCol;
						for(int l=0;l<ptus.size();l++){
							ptu = ptus.elementAt(l);
							center = ptu.getCenterPosition();
							shapeCol = ptu.getColor();
							bgCol = ptu.getBgColor();
							flashCol = ptu.getBgHlColor();
							sb.append(center.x+","+center.y+";"+ptu.getRadius()+";"+shapeCol.getRed()+","+shapeCol.getGreen()+","+shapeCol.getBlue()+";"+bgCol.getRed()+","+bgCol.getGreen()+","+bgCol.getBlue()+";"+flashCol.getRed()+","+flashCol.getGreen()+","+flashCol.getBlue()+";");
							if(ptu.hasTADEs()){
								Vector<TADE> tades = ptu.getPictureTags();
								TADE tade;
								Point p;
								String type;
								Color c,fc;
								for(int m=0;m<tades.size();m++){
									tade = tades.elementAt(m);
									type = tade.getType();
									p = tade.getPoint();
									c = tade.getColor();
									fc = tade.getFlashColor();
									sb.append(type+"="+p.x+","+p.y+"="+c.getRed()+","+c.getGreen()+","+c.getBlue()+"="+fc.getRed()+","+fc.getGreen()+","+fc.getBlue()+"%");
								}
								sb.append(">");
							}
							else sb.append("~>");
						}
						sb.append("<");
					}
				}
				else sb.append("~");
				try{
					BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(pathOfCollection+File.separator+name+File.separator+"data"),"UTF-8"));
					writer.write(sb.toString());
					writer.close();
				}
				catch(Exception e){
					e.printStackTrace();
					return false;
				}
			}
			else{
				JLabel msgLabel = new JLabel("<HTML><BODY>Cannot save data for picture map: "+colName+"/"+name+"<br>No write permission for file:");
				JLabel pathLabel = new JLabel(pathOfCollection+File.separator+name+File.separator+"data");
				JPanel msgPanel = new JPanel();
				msgPanel.setLayout(new BoxLayout(msgPanel,BoxLayout.Y_AXIS));
				msgPanel.add(msgLabel);
				msgPanel.add(pathLabel);
				JOptionPane.showMessageDialog(null, msgPanel, "Error", JOptionPane.ERROR_MESSAGE);
				return false;
			}
			return true;
		}
		return false;
	}
	
	/*public void saveCollsection(String col){
		if(hasCollections()&&!LOADING){
			if(SET.isVerbose()) System.out.println("#SAVING COLLECTION: "+col);
			PictureCollection tmpColl = getCollection(col);
			if(tmpColl.hasPictures()){
				Vector<PictureUnit> units = tmpColl.getPictureUnits();
				for(PictureUnit unit : units){
					saveUnit(col,unit);
				}
			}
		}
	}
	
	public void sasve(){
		if(hasCollections()&&!LOADING){
			if(SET.isVerbose()) System.out.println("#SAVING ALL COLLECTIONS");
			for(int i=0;i<COLLECTIONS.size();i++){
				saveCollection(COLLECTIONS.elementAt(i).getName());
			}
			saveLessons();
		}
	}*/
	
	public void saveLessons(){
		if(SET.isVerbose()) System.out.print("#SAVING COLLECTION LESSONS...");
		if(!LESSONS.isEmpty()){
			try{
				BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("settings"+File.separator+"pictureLessons.trib"),"UTF-8"));
				StringBuffer sb = new StringBuffer();
				String[] lessonNames = LESSONS.keySet().toArray(new String[]{});
				Lesson lesson;
				PictureCollection collection;
				for(String name : lessonNames){
					sb.append(name+"=");
					lesson = LESSONS.get(name);
					if(lesson.hasUnits()){
						for(String coll : lesson.getCollectionNames()){
							sb.append(coll+":");
							collection = getCollection(coll);
							for(String pu : lesson.getUnitNames(coll)){
								if(collection.hasPicture(pu))sb.append(pu+">");
							}
							sb.append(";");
						}
					}
					else{
						sb.append("~");
					}
					sb.append("#");
				}
				writer.write(sb.toString());
				writer.close();
				if(SET.isVerbose()) System.out.println("successfully");
			}
			catch(Exception e){
				if(SET.isVerbose()){
					System.out.println("FAILED !");
					e.printStackTrace();
				}
			}
		}
		else{
			if(SET.isVerbose()) System.out.print("No lesson data, deleting pictureLessons.trib ");
			try{
				File f = new File("settings"+File.separator+"pictureLessons.trib");
				if(f.exists()){
					if(f.delete()){
						if(SET.isVerbose()) System.out.println("successfully.");
					}
					else if(SET.isVerbose()) System.out.println("FAILED!");
				}
			}
			catch(Exception e){
				if(SET.isVerbose()){
					System.out.println("ERROR DURING DELETING pictureLessons.trib !");
					e.printStackTrace();
				}
			}
		}
	}
	
	public void loadLessons(){
		File f = new File("settings"+File.separator+"pictureLessons.trib");
		if(f.exists()){
			try{
				BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(f),"UTF-8"));
				String line = null, loads = "";
				while((line = reader.readLine()) != null){
					loads=loads+line;
				}
				reader.close();
				String[] lessons = loads.split("#"), split1,split2,split3,split4;
				Lesson l;
				for(String lesson : lessons){
					if(lesson.equals(null) && !lesson.equals("")){
						split1 = lesson.split("=");
						LESSONS.put(split1[0], new Lesson(this));
						if(split1[1]!=null && !split1[1].equals("") && !split1[1].equals("~")){
							l = LESSONS.get(split1[0]);
							split2 = split1[1].split(";");
							for(String coll : split2){
								split3 = coll.split(":");
								split4 = split3[1].split(">");
								for(String pu : split4){
									if(pu!=null && !pu.equals(""))l.addUnit(split3[0], pu);
								}
							}
						}
					}
				}
			}
			catch(Exception e){
				e.printStackTrace();
			}
		}
	}

	public boolean hasLessons(){
		return LESSONS.isEmpty();
	}
	
	public HashMap<String,Lesson> getLessons(){
		return LESSONS;
	}
	
	public Lesson getLesson(String lesson){
		return LESSONS.get(lesson);
	}
	
	public void createLesson(String name){
		if(!LESSONS.containsKey(name))LESSONS.put(name, new Lesson(this));
	}
	
	public void deleteLesson(String name){
		if(LESSONS.containsKey(name))LESSONS.remove(name);
	}
	
	public void deleteCollectionFromLessons(String name){
		if(!LESSONS.isEmpty()){
			for(String key : LESSONS.keySet().toArray(new String[]{})){
				LESSONS.get(key).deleteCollection(name);
			}
		}
	}
	
	public void alterUnitNameInLessons(String oc, String on, String nc, String nn){
		if(!LESSONS.isEmpty()){
			for(String key : LESSONS.keySet().toArray(new String[]{})){
				LESSONS.get(key).alterUnitName(oc,on,nc,nn);
			}
		}
		saveLessons();
	}
	
	public void deleteUnitFromLessons(String col, String pu){
		if(!LESSONS.isEmpty()){
			Lesson l;
			for(String lesson : LESSONS.keySet().toArray(new String[]{})){
				l = LESSONS.get(lesson);
				if(l.hasUnits()){
					l.deleteUnitFromCollection(col, pu, true);
				}
			}
		}
		saveLessons();
	}
	
	public void changeCollectionNameInLessons(String oldName, String newName){
		if(!LESSONS.isEmpty()){
			for(String key : LESSONS.keySet().toArray(new String[]{})){
				LESSONS.get(key).changeCollectionName(oldName, newName);
			}
		}
	}
	
	public void setLessons(HashMap<String, Lesson> newLessons){
		LESSONS = newLessons;
	}
}
